
package edu.ntnu.superrss.controller;

import edu.ntnu.superrss.controller.domain.FormCategories;
import edu.ntnu.superrss.controller.domain.FormCategory;
import edu.ntnu.superrss.models.Category;
import edu.ntnu.superrss.models.SyndFeedImpl;
import edu.ntnu.superrss.models.User;
import edu.ntnu.superrss.service.CategoryService;
import edu.ntnu.superrss.service.FeedService;
import edu.ntnu.superrss.service.UserService;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpSession;
import org.hibernate.HibernateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

/**
 * CatecoryController is a controller class for various actions.
 * It uses annotations and auto-wiring i Spring to implement the neccesarry
 * mappings to map the controller to functions and views.
 *
 *
 * @author Dyre Hult <dyre.hult at gmail.com>
 */
@Controller
@SessionAttributes("user")
public class CategoryController {

        private UserService userService;
        private CategoryService categoryService;
        private FeedService feedService;

        @Autowired
        public void setUserService(UserService userService) {
            this.userService = userService;
        }

        @Autowired
        public void setCategoryService(CategoryService categoryService) {
            this.categoryService = categoryService;
        }

        @Autowired
        public void setFeedService(FeedService feedService) {
            this.feedService = feedService;
        }
        /**
        * Maps the category.htm GET to the viewCategory function. Handles GET-data.
        * <p>
        * this method lists categories, if feedId is set, it indicates the categories
        * the feed is related to with checked checkboxes
        *
        *
        * @param feedId    a Long value containing the id of the feed to be shown
        * @param session   the session containing user data
        * @param model     the ModelMap object used to transfer data to the view
        * @return          the String containing the name of the view to return
        */
        @Transactional
	@RequestMapping(value="/category.htm", method=RequestMethod.GET)
	public String viewCategory(@RequestParam(required = false, value = "feedId") Long feedId, ModelMap model, HttpSession session){

            User user = this.userService.getUser((User)session.getAttribute("user"));
            List<Category> categories = new ArrayList(user.getCategories());

            FormCategories formCategories = new FormCategories();
            
            List<Long> checkedCategoryIds = new ArrayList<Long>();
            if (feedId != null) {
                SyndFeedImpl feed = (SyndFeedImpl)user.getFeed(feedId);
                for (Category feedCategory : (List<Category>)feed.getCategories()) {
                    checkedCategoryIds.add(feedCategory.getId());
                }

                formCategories.setCategoryIds((Long[])checkedCategoryIds.toArray(new Long[checkedCategoryIds.size()]));
                formCategories.setFeedId(feedId);
            }

            model.addAttribute("title", "My categories");
            model.addAttribute("categories", categories);
            model.addAttribute("formCategory", new FormCategory());
            model.addAttribute("formCategories", formCategories);

            return "category";
	}
        /**
        * Maps the category.htm POST to the addCategory function. Handles POST-data.
        * <p>
        * Adds the category specified in the formCategory object.
        * if feedId is set, will add it to the model, so that it will be handeled correctly by viewCategories
        *
        * @param feedId    a Long value containing the id of the feed to be added
        * @param formCategory A pojo containing the categories.
        * @param session   the session containing user data
        * @param model     the ModelMap object used to transfer data to the view
        * @return          the String containing the name of the view to return
        */
	@RequestMapping(value="/category.htm", method=RequestMethod.POST)
	public String addCategory(
            @RequestParam(required = false, value = "feedId") Long feedId,
            @ModelAttribute("formCategory") FormCategory formCategory,
            ModelMap model,
            HttpSession session
        ) {
            User user = this.userService.getUser((User)session.getAttribute("user"));

            if (formCategory.getTitle() != null) {
                Category category = new Category(formCategory.getTitle());
                category.setUser(user);
                this.categoryService.addCategory(user, category);
            }

            model.addAttribute("feedId", feedId);
            return "redirect:category.htm";
	}
        /**
        * Maps the categories.htm POST to the relateFeedWithCategories function. Handles POST-data.
        * <p>
        * this method adds the feed specified in formCategories, to the categories specified in formCategories
        *
        * @param formCategois A pojo containing the categories and feedid
        * @param session   the session containing user data
        * @param model     the ModelMap object used to transfer data to the view
        * @return          the String containing the name of the view to return
        */
        @RequestMapping(value="/categories.htm", method=RequestMethod.POST)
        public String relateFeedWithCategories(
            @ModelAttribute("formCategories") FormCategories formCategories,
            ModelMap model,
            HttpSession session
        ) {
            if ((formCategories.getFeedId() != null) && (formCategories.getCategoryIds().length > 0)) {
                User user = this.userService.getUser((User)session.getAttribute("user"));
                List categories = this.categoryService.getCategories(formCategories.getCategoryIds());
                SyndFeedImpl feed = (SyndFeedImpl)user.getFeed(formCategories.getFeedId());

                feed.setCategories(categories);
                this.feedService.updateFeed(feed);
            } else {
                model.addAttribute("errors", "Feed or categories was no selected");
            }

            return "redirect:feeds.htm";
        }
        /**
        * Maps the remove-category.htm GET to the removeCategory function. Handles GET-data.
        * <p>
        * Removes the category specified by the id parameter
        *
        * @param id        a Long containing the category id
        * @param session   the session containing user data
        * @param model     the ModelMap object used to transfer data to the view
        * @return          the String containing the name of the view to return
        */
    @RequestMapping(value = "/remove-category.htm", method = RequestMethod.GET)
    public String removeCategory(@RequestParam("id") Long id, HttpSession session, ModelMap model) {
        Logger.getLogger(FeedController.class.getName()).log(Level.INFO, "CategoryController:removeCategory called");

        User user = this.userService.getUser((User)session.getAttribute("user"));
        if (user == null) {
            Logger.getLogger(FeedController.class.getName()).log(Level.INFO, "CategoryController:removeCategory FAILED:Could not get the user info from the session");
            model.addAttribute("errors", "Missing user info");
            return "redirect:category.htm";
        }

        try {
            this.categoryService.removeCategory(user, id);
        } catch (NullPointerException e) {
            Logger.getLogger(FeedController.class.getName()).log(Level.INFO, "CategoryController:removeCategory FAILED:Could not find the user in the datasbase", e);
            model.addAttribute("errors", "Something was null");
            model.addAttribute("errors", e.toString());
        } catch (HibernateException e) {
            Logger.getLogger(FeedController.class.getName()).log(Level.INFO, "CategoryController:removeCategory FAILED:", e);
            model.addAttribute("errors", "Hibernate failed");
            model.addAttribute("errors", e.toString());
        } catch (Exception e) {
            Logger.getLogger(FeedController.class.getName()).log(Level.INFO, "CategoryController:removeCategory FAILED:", e);
            model.addAttribute("errors", "Something failed");
            model.addAttribute("errors", e.toString());
        }
        return "redirect:category.htm";
    }
}